package controller;

import java.io.File;
import java.util.ArrayList;

import model.Project;
import modelInterfaces.AbstractModelFactory;
import modelInterfaces.IProject;
import modelInterfaces.ITest;
import pluginInterfaces.IMetric;
import pluginInterfaces.IRecommender;
import view.ViewMain;
import view.ViewProjectManagement;
import viewInterfaces.AbstractViewFactory;
import viewInterfaces.IViewMain;
import viewInterfaces.IViewProjectManagement;
import controllerInterfaces.IControllerMain;
import controllerInterfaces.IControllerProjectManagement;
import enums.StatusProject;
import enums.Use;

/**
 * Controls and manage the current {@link Project}
 * @see Project
 * @see IProject   
 */
public class ControllerProjectManagement implements IControllerProjectManagement {

	/** MVC++ Main Controller
	* @see ControllerMain*/
	private IControllerMain mainController;
	
	/** Action over project*/
	private Use use;
	
	/** View of Project Management
	 * @see ViewProjectManagement*/
	private IViewProjectManagement view;
	
	/**
	 * Class Constructor */
	public ControllerProjectManagement() {
		this.view = AbstractViewFactory.getAbstractViewFactory().getViewProjectManagement();
		this.view.setController(this);
	}
	
	
	/**
	 * Set the MVC++ Main Class for this controller.</br>
	 * ControllerMain is manipulable through {@link IControllerMain} interface
	 * @param	controllerMain	MVC++ Main Controller
	 * @see	ControllerMain
	 * @see IControllerMain
	 */	
	public void setMainController(IControllerMain maincontroller) {
		this.mainController = maincontroller;
	}	
	
	/**
	 * Set the {@link Use} of project
	 * @param	use	Action over project
	 */	
	public void SetUse(Use use) {
		this.use = use;
	}

	/**
	 * Performs action such as create, load, save a {@link Project} from file.
	 * @see Project
	 */
	public void load()
	{

		 if (this.use != null)
		 {
			if (this.use == Use.New)
			{
				view.New();
			}
			else if (this.use == Use.Load)
			{
				IProject project = AbstractModelFactory.getModelFactory().getProject();
				project = (IProject) this.view.Load();
				loadProject(project);
			}
			else if (this.use == Use.Save)
			{
				if (mainController.GetSelectedFile() == null)// When project yet is not saved in a file
				{
					if (this.view.Save((Object) mainController.getProject()))
					{
						mainController.getProject().setStatus(StatusProject.Saved);
						mainController.StatusProjectSaved();
					}
				}
				else // When project is saved in a file
				{
					if (this.view.Save((Object) mainController.getProject(), mainController.GetSelectedFile()))
					{
						mainController.getProject().setStatus(StatusProject.Saved);
						mainController.StatusProjectSaved();
					}
				}
			}
			else if (this.use == Use.SaveAs)
			{
				if (this.view.Save((Object) mainController.getProject()))
				{
					mainController.getProject().setStatus(StatusProject.Saved);
					mainController.StatusProjectSaved();
				}
			}
		}
		else
		{
			System.out.println("Use not setted");
		}
	}


	/**
	 * Get the MVC++ Main View Main from {@link ControllerMain}.</br>
	 * The obtained main view is manipulable through its {@link IViewMain} interface.
	 * @return	main view
	 * @see		ViewMain
	 * @see		IViewMain
	 * @see		ControllerMain
	 */
	public IViewMain getViewMain() {
		return this.mainController.getViewMain();
	}
	
	
	/**
	 * Create a new project with name according to parameter name.
	 * @param	name	project name  
	 */	
	public void createProject(String name)
	{
		IProject project = AbstractModelFactory.getModelFactory().getProject();
		project.setName(name);
		project.setStatus(StatusProject.New);
		project.setRecommenderList(new ArrayList<IRecommender>());
		project.setMetricList(new ArrayList<IMetric>());
		project.setTestList(new ArrayList<ITest>());
		this.mainController.setProject(project);
		this.mainController.StatusProjectCreated();
	}
	

	
	/**
	 * Load a existing project  according to parameter project.
	 * @param	project	project object  
	 */		
	private void loadProject(IProject project)
	{
		if (project != null)
		{
			mainController.setProject(project);
			mainController.setProjectNameInView(this.mainController.getProject().getName());
			mainController.setProjectStatus(true, StatusProject.Opened);
		}
		mainController.stopProjectManagement();
	}

	
	/**
	 * Set selected file associated with {@link Project}. 
	 * @param oi object input stream.
	 * @see Project
	 */
	public void SetSelectedFile(File sFile){
		this.mainController.SetSelectedFile(sFile);
	}
	
	
	/**
	 * Get View of this controller</br>
	 * This method is only used for realize unit testing.
	 * @return IViewProjectManagement
	 */
	public IViewProjectManagement GetView()
	{
		return this.view;
	}
	
	
}
